﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Runtime.Serialization;
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Linq.Expressions;
using AbstraX.XPathBuilder;
using System.ServiceModel.DomainServices.Client;
using AbstraX.Contracts;
using System.ServiceModel.DomainServices.Server;
using System.ServiceModel;
using AbstraX.TypeMappings;
using MvvmTreeView;


namespace AbstraX.ServerInterfaces
{
    public static class DNSHelper
    {
        public static string MakeURL(string path)
        {
            return "AbstraX://" + DNSHelper.Host + "/" + path;
        }

        public static string Host
        {
            get
            {
                return Dns.GetHostName();
            }
        }
    }

    public interface IAbstraXService
    {
        IDomainHostApplication DomainServiceHostApplication { get; set; }
    }

    public interface IAbstraXProviderServiceChannel
    {
        string GetRootID();
    }

    public interface IAbstraXProviderService : IAbstraXProviderServiceChannel, IAbstraXService
    {
        byte[] GetImageForFolder(string folderKey);
        byte[] GetImageForItemType(string itemTypeName);
        byte[] GetImageForUrl(string url);
        IBase GenerateByID(string id);
        ContainerType GetAllowableContainerTypes(string id);
        ConstructType GetAllowableConstructTypes(string id);
        SortedList<float, IPipelineStep> InitialPipelineSteps { get; }
    }

    public delegate void ChildrenLoadedHandler(IBase parent);

    public enum ProviderType : int
    {
        BusinessModel,
        ViewModel,
        EntityMap,
        AssemblyMap,
        ParsedCode,
        ResourceMap,
        WebService,
        CodeModel,
        ServerModel,
        ODATA,
        JSON,
        ASPX,
        XAML,
        URLDocument,
        HTML,
        XML,
        SQL,
        Custom
    }

    public enum DefinitionKind : int 
    {
        Unknown = 0,
        Class = 1,
        Delegate = 2,
        Enumeration = 3,
        Interface = 4,
        Structure = 5,
        Constructor = -1,
        Event = -2,
        Field = -3,
        Method = -4,
        Operator = -5,
        Property = -6,
        NotApplicable = 100
    }

    public enum NodeType : int
    {
        Root,
        Element,
        Attribute,
        Operation
    }

    public enum OperationDirection : int
    {
        Incoming,
        Outgoing
    }

    public interface IPathQueryable
    {
        void ExecuteWhere(string property, object value);
        void ExecuteWhere(Expression expression);
        void ExecuteWhere(XPathAxisElement element);
        void ClearPredicates();
    }

    public interface IRoot : IBase, IPathQueryable, IDisposable
    {
        string ParentFieldName { get; }
        string URL { get; }
        ProviderType ProviderType { get; }
        BaseType DataType { get; }
        IEnumerable<IElement> RootElements { get; }
        void ExecuteGlobalWhere(XPathAxisElement element);
    }

    [DataContract, KnownType(typeof(ScalarType)), KnownType(typeof(Facet))]
    public class BaseType
    {
        [DataMember, Key]
        public string ID { get; set; }
        [DataMember]
        public string ParentID { get; set; }
        [DataMember]
        public string Name { get; set;  }
        [DataMember]
        public string FullyQualifiedName { get; set; }
        [DataMember]
        public bool IsCollectionType { get; set; }
        [DataMember]
        public BaseType CollectionType { get; set; }
        [DataMember]
        public bool IsImageType { get; set; }
        [DataMember]
        public bool IsAbstract { get; set; }
        [DataMember]
        public string SuggestedNamespace { get; set; }
    }

    [DataContract]
    public class Argument
    {
        [DataMember, Key]
        public string ID { get; set; }
        [DataMember]
        public string ParentID { get; set; }
        [DataMember]
        public string Value { get; set; }
    }

    [DataContract]
    public class Facet
    {
        [DataMember, Key]
        public string ID { get; set; }
        [DataMember]
        public string ParentID { get; set; }
        [DataMember, Include, Association("Facet_FacetType", "ID", "ParentID")]
        public BaseType FacetType { get; set; }
        [DataMember, Include, Association("Facet_Arguments", "ID", "ParentID")]
        public Argument[] Arguments { get; set; }
        [DataMember]
        public string AttributeCode
        {
            get
            {
                return FacetType.Name + "(" + Arguments.Select(a => a.Value).ToCommaDelimitedList() + ")";
            }
        }
    }

    [DataContract]
    public class ScalarType : BaseType
    {
        [DataMember]
        public int TypeCode { get; set;  }
    }

    public interface IParentBase : IBase, IPathQueryable
    {
        IEnumerable<IElement> ChildElements { get; }
        IRoot Root { get; }
    }

    public interface IBase 
    {
        string ID { get; }
        string ParentID { get; }
        string Name { get; }
        string Description { get; }
        string Documentation { get; }
        string ImageURL { get; }
        float ChildOrdinal { get; }
        string DebugInfo { get; }
        IBase Parent { get; }
        string FolderKeyPair { get; set; }
        DefinitionKind Kind { get; }
        bool HasChildren { get; }
        Facet[] Facets { get; }
    }

    public interface IAttribute : IParentBase 
    {
        ScalarType DataType { get; }
    }

    public interface IOperation : IParentBase
    {
        OperationDirection Direction { get; }
    }

    public interface IElement : IParentBase 
    {
        bool IsContainer { get; }
        BaseType DataType { get; }
        IEnumerable<IAttribute> Attributes { get; }
        IEnumerable<IOperation> Operations { get; }
        ContainerType DefaultContainerType { get; }
        ConstructType DefaultConstructType { get; }
        ContainerType AllowableContainerTypes { get; }
        ConstructType AllowableConstructTypes { get; }
    }
}
